package com.linkoog.devtools.code_generator.wizard.generate.database.template.tree;

import com.linkoog.devtools.code_generator.CodeGenIcons;
import com.linkoog.devtools.code_generator.template.model.node.FileNodeData;
import com.linkoog.devtools.code_generator.template.model.node.DirNodeData;
import com.linkoog.devtools.code_generator.template.model.node.TemplateNodeData;
import com.linkoog.devtools.code_generator.util.FileTypeUtil;
import com.intellij.icons.AllIcons;
import com.intellij.icons.AllIcons.Nodes;
import com.intellij.openapi.fileTypes.FileType;

import javax.swing.*;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;

/**
 * 复选框的树形渲染
 */
@SuppressWarnings("serial")
public class CheckBoxTreeCellRenderer extends JPanel implements TreeCellRenderer {

    protected JCheckBox check;

    protected CheckBoxTreeLabel label;

    // Icons
    /** Icon used to show non-leaf nodes that aren't expanded. */
    transient protected Icon closedIcon;

    /** Icon used to show leaf nodes. */
    transient protected Icon leafIcon;

    /** Icon used to show non-leaf nodes that are expanded. */
    transient protected Icon openIcon;


    public CheckBoxTreeCellRenderer() {
        setLayout(null);
        add(check = new JCheckBox());
        check.setBackground(UIManager.getColor("Tree.textBackground"));
        check.setOpaque(false);

        add(label = new CheckBoxTreeLabel());
        label.setForeground(UIManager.getColor("Tree.textForeground"));
    }

    /**
     * 返回的是一个<code>JPanel</code>对象，该对象中包含一个<code>JCheckBox</code>对象
     * 和一个<code>JLabel</code>对象。并且根据每个结点是否被选中来决定<code>JCheckBox</code>
     * 是否被选中。
     */
    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {

        setEnabled(tree.isEnabled());
        CheckBoxTreeNode checkBoxTreeNode = (CheckBoxTreeNode) value;
        check.setSelected(checkBoxTreeNode.isSelected());
        if (checkBoxTreeNode.isSelected()){
            if (checkBoxTreeNode.isChildrenAllSelected()){
                check.setSelectedIcon(CodeGenIcons.CheckBox.checked);
                //check = new JCheckBox(CheckBox.checked, true);
            }else {
                check.setSelectedIcon(CodeGenIcons.CheckBox.partial);
                //check = new JCheckBox(CheckBox.partial, true);
            }


        }else {
            check.setIcon(CodeGenIcons.CheckBox.unchecked);
            //check = new JCheckBox(CheckBox.unchecked, false);
        }
        //this.updateUI();
        this.repaint();


        label.setFont(tree.getFont());
        label.setSelected(selected);
        label.setFocus(hasFocus);

        Object obj = checkBoxTreeNode.getUserObject();
        if (obj instanceof TemplateNodeData) {
            TemplateNodeData rootNode = (TemplateNodeData) obj;
            this.setOpenIcon(AllIcons.Nodes.JavaModule);
            this.setClosedIcon(AllIcons.Nodes.JavaModule);
            this.setLeafIcon(AllIcons.Nodes.JavaModule);
            label.setText(rootNode.getName());
        }
        else if (obj instanceof DirNodeData) {
            DirNodeData packageNode = (DirNodeData) obj;
            this.setOpenIcon(Nodes.Package);
            this.setClosedIcon(Nodes.Package);
            this.setLeafIcon(Nodes.Package);
            label.setText(packageNode.getName());
        }
        else if (obj instanceof FileNodeData) {
            FileNodeData fileNode = (FileNodeData) obj;
            FileType fileType = FileTypeUtil.getFileType(fileNode.getType());
            this.setOpenIcon(fileType.getIcon());
            this.setClosedIcon(fileType.getIcon());
            this.setLeafIcon(fileType.getIcon());
            label.setText(fileNode.getName());
        } else {
            String text = tree.convertValueToText(value, selected, expanded, leaf, row, hasFocus);
            this.setOpenIcon(AllIcons.Nodes.JavaModule);
            this.setClosedIcon(AllIcons.Nodes.JavaModule);
            this.setLeafIcon(AllIcons.Nodes.JavaModule);
            label.setText(text);
        }


        if (leaf){
            label.setIcon(this.leafIcon);
        } else if (expanded){
            label.setIcon(this.openIcon);
        } else{
            label.setIcon(this.closedIcon);
        }

        label.setOpaque(false);
        this.setOpaque(false);
        return this;
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension dCheck = check.getPreferredSize();
        Dimension dLabel = label.getPreferredSize();
        return new Dimension(dCheck.width + dLabel.width + 5, Math.max(dCheck.height, dLabel.height));
    }

    @Override
    public void doLayout() {
        Dimension dCheck = check.getPreferredSize();
        Dimension dLabel = label.getPreferredSize();
        int yCheck = 0;
        int yLabel = 0;
        if (dCheck.height < dLabel.height) {
            yCheck = (dLabel.height - dCheck.height) / 2;
        } else {
            yLabel = (dCheck.height - dLabel.height) / 2;
        }
        check.setLocation(0, yCheck);
        check.setBounds(0, yCheck, dCheck.width, dCheck.height);
        label.setLocation(dCheck.width + 5, yLabel);
        label.setBounds(dCheck.width+ 5, yLabel, dLabel.width+ 5, dLabel.height);
    }

    public void setClosedIcon(Icon closedIcon) {
        this.closedIcon = closedIcon;
    }

    public void setLeafIcon(Icon leafIcon) {
        this.leafIcon = leafIcon;
    }

    public void setOpenIcon(Icon openIcon) {
        this.openIcon = openIcon;
    }


    private static class MyJCheckBox extends JCheckBox{

        public MyJCheckBox(){
            this.setIcon(CodeGenIcons.CheckBox.unchecked);
            this.setSelectedIcon(CodeGenIcons.CheckBox.checked);
        }

        public void setSelected(boolean selected, boolean childrenAllSelected){
            if (selected){
                Icon oldValue = this.getSelectedIcon();
                Icon selectedIcon;

                if (childrenAllSelected){
                    selectedIcon = CodeGenIcons.CheckBox.checked;
                }else {
                    selectedIcon = CodeGenIcons.CheckBox.partial;
                }
                this.setSelectedIcon(selectedIcon);
                firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, this.getSelectedIcon(), selectedIcon);
            }
        }

    }

}